﻿using System;
using System.ComponentModel;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace PMP.Core.Extensions;

public class JsonObjectToSimpleTypeBinder : IModelBinder
{
    private readonly IModelBinder _fallbackBinder;

    public JsonObjectToSimpleTypeBinder(IModelBinder fallbackBinder)
    {
        _fallbackBinder = fallbackBinder;
    }

    public async Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var httpContext = bindingContext.HttpContext;
        var request = httpContext.Request;

        // 仅处理 POST/PUT/PATCH 且 Content-Type 为 application/json 的请求
        if (!IsValidRequest(request))
        {
            await _fallbackBinder.BindModelAsync(bindingContext);
            return;
        }

        try
        {
            // 从 HttpContext.Items 中获取缓存的 JSON 解析结果（避免重复解析）
            if (!httpContext.Items.TryGetValue("ParsedJson", out var jsonDocObj) || jsonDocObj is not JsonDocument jsonDoc)
            {
                // 第一次读取：重置流位置并读取完整内容
                request.Body.Position = 0;
                using var reader = new StreamReader(request.Body);
                var json = await reader.ReadToEndAsync();
                if (string.IsNullOrEmpty(json))
                {
                    await _fallbackBinder.BindModelAsync(bindingContext);
                    return;
                }

                // 解析 JSON 并缓存到 HttpContext.Items
                jsonDoc = JsonDocument.Parse(json);
                httpContext.Items["ParsedJson"] = jsonDoc;

                // 关键：重置流位置，确保后续可能的读取（如其他中间件）能正常工作
                request.Body.Position = 0;
            }

            // 从缓存的 JSON 中提取当前参数的值
            var root = jsonDoc.RootElement;
            if (root.TryGetProperty(bindingContext.FieldName, out var property))
            {
                var value = property.ToString();
                if (TypeDescriptor.GetConverter(bindingContext.ModelType).IsValid(value))
                {
                    var convertedValue = TypeDescriptor.GetConverter(bindingContext.ModelType).ConvertFromString(value);
                    bindingContext.Result = ModelBindingResult.Success(convertedValue);
                    return;
                }
            }
        }
        catch
        {
            // 解析失败时使用默认绑定器
        }

        await _fallbackBinder.BindModelAsync(bindingContext);
    }

    // 判断是否为需要处理的请求类型
    private bool IsValidRequest(HttpRequest request)
    {
        var method = request.Method;
        if (method != "POST" && method != "PUT" && method != "PATCH")
            return false;

        return request.ContentType?.StartsWith("application/json", StringComparison.OrdinalIgnoreCase) ?? false;
    }
}